/**
 */
package org.aphelie.chronicle.impl;

import java.lang.reflect.InvocationTargetException;
import java.util.Collection;

import org.aphelie.chronicle.ArcCategory;
import org.aphelie.chronicle.ArcScore;
import org.aphelie.chronicle.ArcShape;
import org.aphelie.chronicle.ArcSheet;
import org.aphelie.chronicle.ArcTopic;
import org.aphelie.chronicle.ArcType;
import org.aphelie.chronicle.ChronicleFactory;
import org.aphelie.chronicle.ChroniclePackage;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.util.EObjectContainmentEList;
import org.eclipse.emf.ecore.util.InternalEList;

/**
 * <!-- begin-user-doc --> An implementation of the model object '
 * <em><b>Arc Shape</b></em>'. <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 *   <li>{@link org.aphelie.chronicle.impl.ArcShapeImpl#getType <em>Type</em>}</li>
 *   <li>{@link org.aphelie.chronicle.impl.ArcShapeImpl#getDefaultScore <em>Default Score</em>}</li>
 *   <li>{@link org.aphelie.chronicle.impl.ArcShapeImpl#getShapes <em>Shapes</em>}</li>
 *   <li>{@link org.aphelie.chronicle.impl.ArcShapeImpl#isOptional <em>Optional</em>}</li>
 *   <li>{@link org.aphelie.chronicle.impl.ArcShapeImpl#getRefid <em>Refid</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public class ArcShapeImpl extends ArcElementImpl implements ArcShape {
	/**
	 * The default value of the '{@link #getType() <em>Type</em>}' attribute.
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @see #getType()
	 * @generated
	 * @ordered
	 */
	protected static final ArcType TYPE_EDEFAULT = ArcType.TEXT;

	/**
	 * The cached value of the '{@link #getType() <em>Type</em>}' attribute.
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @see #getType()
	 * @generated
	 * @ordered
	 */
	protected ArcType type = TYPE_EDEFAULT;

	/**
	 * The default value of the '{@link #getDefaultScore() <em>Default Score</em>}' attribute.
	 * <!-- begin-user-doc --> <!--
	 * end-user-doc -->
	 * @see #getDefaultScore()
	 * @generated
	 * @ordered
	 */
	protected static final int DEFAULT_SCORE_EDEFAULT = 0;

	/**
	 * The cached value of the '{@link #getDefaultScore() <em>Default Score</em>}' attribute.
	 * <!-- begin-user-doc --> <!--
	 * end-user-doc -->
	 * @see #getDefaultScore()
	 * @generated
	 * @ordered
	 */
	protected int defaultScore = DEFAULT_SCORE_EDEFAULT;

	/**
	 * The cached value of the '{@link #getShapes() <em>Shapes</em>}' containment reference list.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getShapes()
	 * @generated
	 * @ordered
	 */
	protected EList<ArcShape> shapes;

	/**
	 * The default value of the '{@link #isOptional() <em>Optional</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #isOptional()
	 * @generated
	 * @ordered
	 */
	protected static final boolean OPTIONAL_EDEFAULT = false;

	/**
	 * The cached value of the '{@link #isOptional() <em>Optional</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #isOptional()
	 * @generated
	 * @ordered
	 */
	protected boolean optional = OPTIONAL_EDEFAULT;

	/**
	 * The default value of the '{@link #getRefid() <em>Refid</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getRefid()
	 * @generated
	 * @ordered
	 */
	protected static final String REFID_EDEFAULT = null;

	/**
	 * The cached value of the '{@link #getRefid() <em>Refid</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getRefid()
	 * @generated
	 * @ordered
	 */
	protected String refid = REFID_EDEFAULT;

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	protected ArcShapeImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return ChroniclePackage.Literals.ARC_SHAPE;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	public ArcType getType() {
		return type;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setType(ArcType newType) {
		ArcType oldType = type;
		type = newType == null ? TYPE_EDEFAULT : newType;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, ChroniclePackage.ARC_SHAPE__TYPE, oldType, type));
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	public int getDefaultScore() {
		return defaultScore;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated NOT
	 */
	public ArcTopic shape(ArcSheet sheet) {
		for (ArcShape shape : getShapes()) {
			if (shape.isOptional() == false) {
				sheet.getTopics().add(shape.shape());
			}
		}
		return null;
	}
	
	private boolean isCategory() {
		return getShapes() != null && getShapes().size() > 0;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * 
	 * @generated NOT
	 */
	public ArcTopic shape() {
		return shape(false);
	}
	
	public ArcTopic shape(boolean shapeOptionals) {
		ArcTopic topic;
		if (isCategory()) {
			topic = shapeCategory(shapeOptionals);
		} else {
			topic = shapeScore(shapeOptionals);
		}
		topic.setId(getId());
		return topic;
	}
	
	private ArcCategory shapeCategory(boolean shapeOptionals) {
		ArcCategory category = ChronicleFactory.eINSTANCE
				.createArcCategory();
		for (ArcShape shape : getShapes()) {
			if (shape.isOptional() == shapeOptionals) {
				category.getTopics().add(shape.shape());
			}
		}
		return category;
	}
	
	private ArcScore shapeScore(boolean shapeOptionals) {
		ArcScore score = ChronicleFactory.eINSTANCE.createArcScore();
		score.setValue(getDefaultScoreValue());
		return score;
	}

	private int getDefaultScoreValue() {
		ArcShape shape = this;
		int value = getDefaultScore();
		while (value < 1) {
			shape = (ArcShape) shape.eContainer();
			if (shape == null) {
				return value;
			}
			value = shape.getDefaultScore();
		}
		return value;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	public void setDefaultScore(int newDefaultScore) {
		int oldDefaultScore = defaultScore;
		defaultScore = newDefaultScore;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, ChroniclePackage.ARC_SHAPE__DEFAULT_SCORE, oldDefaultScore, defaultScore));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EList<ArcShape> getShapes() {
		if (shapes == null) {
			shapes = new EObjectContainmentEList<ArcShape>(ArcShape.class, this, ChroniclePackage.ARC_SHAPE__SHAPES);
		}
		return shapes;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public boolean isOptional() {
		return optional;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setOptional(boolean newOptional) {
		boolean oldOptional = optional;
		optional = newOptional;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, ChroniclePackage.ARC_SHAPE__OPTIONAL, oldOptional, optional));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public String getRefid() {
		return refid;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setRefid(String newRefid) {
		String oldRefid = refid;
		refid = newRefid;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, ChroniclePackage.ARC_SHAPE__REFID, oldRefid, refid));
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public NotificationChain eInverseRemove(InternalEObject otherEnd,
			int featureID, NotificationChain msgs) {
		switch (featureID) {
			case ChroniclePackage.ARC_SHAPE__SHAPES:
				return ((InternalEList<?>)getShapes()).basicRemove(otherEnd, msgs);
		}
		return super.eInverseRemove(otherEnd, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
			case ChroniclePackage.ARC_SHAPE__TYPE:
				return getType();
			case ChroniclePackage.ARC_SHAPE__DEFAULT_SCORE:
				return getDefaultScore();
			case ChroniclePackage.ARC_SHAPE__SHAPES:
				return getShapes();
			case ChroniclePackage.ARC_SHAPE__OPTIONAL:
				return isOptional();
			case ChroniclePackage.ARC_SHAPE__REFID:
				return getRefid();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
			case ChroniclePackage.ARC_SHAPE__TYPE:
				setType((ArcType)newValue);
				return;
			case ChroniclePackage.ARC_SHAPE__DEFAULT_SCORE:
				setDefaultScore((Integer)newValue);
				return;
			case ChroniclePackage.ARC_SHAPE__SHAPES:
				getShapes().clear();
				getShapes().addAll((Collection<? extends ArcShape>)newValue);
				return;
			case ChroniclePackage.ARC_SHAPE__OPTIONAL:
				setOptional((Boolean)newValue);
				return;
			case ChroniclePackage.ARC_SHAPE__REFID:
				setRefid((String)newValue);
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
			case ChroniclePackage.ARC_SHAPE__TYPE:
				setType(TYPE_EDEFAULT);
				return;
			case ChroniclePackage.ARC_SHAPE__DEFAULT_SCORE:
				setDefaultScore(DEFAULT_SCORE_EDEFAULT);
				return;
			case ChroniclePackage.ARC_SHAPE__SHAPES:
				getShapes().clear();
				return;
			case ChroniclePackage.ARC_SHAPE__OPTIONAL:
				setOptional(OPTIONAL_EDEFAULT);
				return;
			case ChroniclePackage.ARC_SHAPE__REFID:
				setRefid(REFID_EDEFAULT);
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
			case ChroniclePackage.ARC_SHAPE__TYPE:
				return type != TYPE_EDEFAULT;
			case ChroniclePackage.ARC_SHAPE__DEFAULT_SCORE:
				return defaultScore != DEFAULT_SCORE_EDEFAULT;
			case ChroniclePackage.ARC_SHAPE__SHAPES:
				return shapes != null && !shapes.isEmpty();
			case ChroniclePackage.ARC_SHAPE__OPTIONAL:
				return optional != OPTIONAL_EDEFAULT;
			case ChroniclePackage.ARC_SHAPE__REFID:
				return REFID_EDEFAULT == null ? refid != null : !REFID_EDEFAULT.equals(refid);
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eInvoke(int operationID, EList<?> arguments)
			throws InvocationTargetException {
		switch (operationID) {
			case ChroniclePackage.ARC_SHAPE___SHAPE__ARCSHEET:
				return shape((ArcSheet)arguments.get(0));
			case ChroniclePackage.ARC_SHAPE___SHAPE:
				return shape();
		}
		return super.eInvoke(operationID, arguments);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public String toString() {
		if (eIsProxy()) return super.toString();

		StringBuffer result = new StringBuffer(super.toString());
		result.append(" (type: ");
		result.append(type);
		result.append(", defaultScore: ");
		result.append(defaultScore);
		result.append(", optional: ");
		result.append(optional);
		result.append(", refid: ");
		result.append(refid);
		result.append(')');
		return result.toString();
	}

} // ArcShapeImpl
